<script>
import { Button, Cascader, CascaderPanel, DatePicker, Input, Option, Select, Tooltip } from 'element-ui'
import cloneDeep from 'lodash/cloneDeep'
import dayjs from 'dayjs'
import { typeOf } from '@/shared/Observer'

export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: 'Search',
  props: { search: { type: Array } },
  data () {
    return {
      defaultProps: {
        size: 'small',
        clearable: true
      },
      searchData: {},
      options: {},
      moreBtnText: '展开更多',
      moreBtnIcon: 'el-icon-caret-bottom',
      needMore: true,
      shortcuts: [{
        text: '今天',
        onClick (picker) {
          const end = dayjs().endOf('day')
          const start = dayjs().startOf('day')
          picker.$emit('pick', [start, end])
        }
      }, {
        text: '最近3天',
        onClick (picker) {
          const end = dayjs().endOf('day')
          const start = dayjs().subtract(2, 'day').startOf('day')
          picker.$emit('pick', [start, end])
        }
      }, {
        text: '最近7天',
        onClick (picker) {
          const end = dayjs().endOf('day')
          const start = dayjs().subtract(6, 'day').startOf('day')
          picker.$emit('pick', [start, end])
        }
      }, {
        text: '最近30天',
        onClick (picker) {
          const end = dayjs().endOf('day')
          const start = dayjs().subtract(29, 'day').startOf('day')
          picker.$emit('pick', [start, end])
        }
      }]
    }
  },
  created () {
    this.searchData = this.search.reduce((obj, item) => {
      if (item.defaultValue || item.defaultValue === 0) { obj[item.key] = item.defaultValue }
      return obj
    }, {})
    this.resetSearchData = cloneDeep(this.searchData)
  },
  methods: {
    getSearchData () {
      return cloneDeep(this.searchData)
    },
    renderInput (h, d) {
      return h(Input, {
        props: { ...this.getProps(d) },
        style: { width: '100%' },
        ref: `search-${d._index}`,
        attrs: { placeholder: d.name, spellcheck: false },
        on: this.getOn(d)
      }
      )
    },
    renderDaterange (h, d) {
      return h(DatePicker, {
        props: {
          defaultTime: ['00:00:00', '23:59:59'],
          ...this.getProps(d),
          type: d.elDateType ?? 'daterange',
          popperClass: 'datePick',
          pickerOptions: { shortcuts: ['datetimerange', 'daterange', undefined].includes(d.elDateType) ? this.shortcuts : undefined, ...d?.pickerOptions }
        },
        class: 'daterange',
        style: { width: '100%' },
        ref: `search-${d._index}`,
        on: this.getOn(d)
      }
      )
    },
    renderCascader (h, d) {
      const option = this.options[d.key] || []
      const renderOption = option.map((t) => {
        let optionSlot
        if (d.formatter) { optionSlot = d.formatter({ h, row: t }) } else { optionSlot = null }
        optionSlot = optionSlot ? [optionSlot] : optionSlot

        const result = h(CascaderPanel, {
          key: d.key,
          label: d.labelKey ? t[d.labelKey] : t.name,
          value: d.valueKey ? t[d.valueKey] : t.code,
          props: {
            label: d.labelKey ? t[d.labelKey] : t.name,
            value: d.valueKey ? t[d.valueKey] : t.code
          }
        },
        optionSlot)
        console.log('1', d, t, option, result)
        return result
      })

      return h(Cascader, {
        props: { ...this.getProps(d), 'popper-append-to-body': false, 'no-data-text': '暂无数据' },
        style: { width: '100%' },
        on: {
          ...this.getOn(d),
          'visible-change': async (flag) => {
            if (!flag) { return }
            if (d.apiCallback) { d.__isLazy__ = true }
            if (!d.__isLazy__ || d.__hasInit__ || !typeOf(d.apiCallback, ['function', 'asyncfunction']) || this.options[d.key] !== undefined) { return }
            const option = await d.apiCallback({ searchData: this.searchData })
            this.$set(this.options, d.key, option)
            d.__hasInit__ = true
          }
        }
      },
      [renderOption]
      )
    },
    renderEnums (h, d) {
      return this.renderSelect(h, d)
    },
    renderSelect (h, d) {
      if (d.type === 'enums' && !this.options[d.key]) { this.$nextTick(() => this.$set(this.options, d.key, this.$enum[d.enumsValue])) }
      // if (d.key === 'orgIds') {
      //   // console.log(!this.options[d.key], d, this.options)
      // }
      if ((d.defaultValue || d.defaultValue === 0) && !this.options[d.key] && d.type !== 'enums') {
        this.$nextTick(async () => {
          const option = await d.apiCallback({ searchData: this.searchData })
          // console.log(option)
          this.$set(this.options, d.key, option)
          if (d.linkSet && typeOf(d.linkSet, ['function', 'asyncfunction'])) {
            const res = await d.linkSet({ value: d.defaultValue, searchData: this.searchData, options: this.options })
            // console.log(res)
            if (res) {
              this.$set(this.searchData, res.key, (res.value === undefined ? this.searchData[res.key] : res.value))
              this.$set(this.options, res.key, res.option && typeOf(res.option, 'array') ? res.option : [])
            }
          }
        })
      }
      const option = this.options[d.key] || []
      const renderOption = option.map((t) => {
        let optionSlot
        if (d.formatter) { optionSlot = d.formatter({ h, row: t }) } else { optionSlot = null }
        optionSlot = optionSlot ? [optionSlot] : optionSlot
        if (d.tooltip) {
          return h(Tooltip, {
            props: {
              content: d.labelKey ? t[d.labelKey] : t.name,
              effect: 'dark',
              placement: 'right-start',
              ...d.tooltipProps
            }
          },
          [h(Option, {
            props: {
              key: d.key,
              label: d.labelKey ? t[d.labelKey] : t.name,
              value: d.valueKey ? t[d.valueKey] : t.code
            }
          }, optionSlot)])
        }
        return h(Option, {
          props: {
            key: d.key,
            label: d.labelKey ? t[d.labelKey] : t.name,
            value: d.valueKey ? t[d.valueKey] : t.code
          }
        },
        optionSlot)
      })
      return h(Select, {
        props: { filterable: true, ...this.getProps(d), popperAppendToBody: false, noDataext: '暂无数据' },
        style: { width: '100%' },
        class: 'selects',
        on: {
          ...this.getOn(d),
          'visible-change': async (flag) => {
            if (!flag) { return }
            if (d.apiCallback) { d.__isLazy__ = true }
            if (!d.__isLazy__ || d.__hasInit__ || !typeOf(d.apiCallback, ['function', 'asyncfunction']) || this.options[d.key] !== undefined) { return }
            const option = await d.apiCallback({ searchData: this.searchData })
            this.$set(this.options, d.key, option)
            d.__hasInit__ = true
          }
        }
      },
      [renderOption]
      )
    },
    getOn (d) {
      return {
        input: async (val) => {
          this.$set(this.searchData, d.key, val)
          if (d.linkSet && typeOf(d.linkSet, ['function', 'asyncfunction'])) {
            const res = await d.linkSet({ value: val, searchData: this.searchData, options: this.options })
            if (res) {
              this.$set(this.searchData, res.key, (res.value === undefined ? this.searchData[res.key] : res.value))
              this.$set(this.options, res.key, res.option && typeOf(res.option, 'array') ? res.option : [])
            }
          }
        }
      }
    },
    getProps (d) {
      const props = { ...this.defaultProps, ...d }
      props.placeholder = d?.name
      props.value = this.searchData[d.key]
      return props
    },
    renderSearchItem (h, d) {
      if (d.hide) return null
      const children = []
      if (['input', 'select', 'daterange', 'enums', 'cascader'].includes(d.type)) {
        const func = this[`render${d.type[0].toUpperCase()}${d.type.slice(1)}`]
        if (func) { children.push(func(h, d)) }
      }
      return children.length ? h('div', { class: { searchItem: true, hide: d.needMore }, style: { width: `${d.width ? d.width : '220px'}` } }, children) : null
    },
    renderBtn (h) {
      const btn1 = h(Button, {
        props: {
          size: 'small',
          icon: 'el-icon-search'
        },
        on: {
          click: () => {
            this.$emit('doSearch', cloneDeep(this.searchData))
          }
        }
      }, '搜索')
      const btn2 = h(Button, {
        props: {
          size: 'small',
          icon: 'el-icon-refresh-right'
        },
        on: {
          click: () => {
            this.refresh()
          }
        }
      }, '重置')
      return h('div', { class: 'searchBtn' }, [btn1, btn2])
    },
    renderNeedMore (h) {
      return h(Button, {
        props: { type: 'text', size: 'small' },
        style: { color: 'rgba(81,90,110)', 'margin-bottom': '10px' },
        on: {
          click: () => {
            this.moreBtnText = !this.needMore ? '展开更多' : '收起更多'
            this.moreBtnIcon = !this.needMore ? 'el-icon-caret-bottom' : 'el-icon-caret-top'
            this.needMore = !this.needMore
            this.search.forEach((t) => {
              if (t.needMore !== undefined) { t.needMore = !t.needMore }
            })
          }
        }
      }, [
        h('span', this.moreBtnText),
        h('i', { class: this.moreBtnIcon })
      ])
    },
    refresh () {
      this.searchData = cloneDeep(this.resetSearchData)
      this.$emit('doSearch', cloneDeep(this.searchData))
    }
  },
  render (h) {
    const { search } = this._props
    const needMoreShow = search.some(t => t.needMore !== undefined)
    if (!search.length) { return null }
    const renderS = search.map((d, i) => {
      d._index = i
      return this.renderSearchItem(h, d)
    }).filter(t => t)
    const renderBtn = this.renderBtn(h)
    const renderNeedMore = needMoreShow ? this.renderNeedMore(h) : null
    return h('div', { class: 'search' }, [renderS, renderBtn, renderNeedMore])
  }
}
</script>

<style scoped lang="less">
.search{
    display:flex;
    flex-wrap:wrap;
    align-items:center;
    .searchBtn{
        margin-bottom:10px;
        margin-right:10px
    }
    .searchItem{
        min-width:220px;
        display:inline-block;
        margin-right:10px;
        margin-bottom:10px
    }
    .hide{
        display:none
    }
    :deep(.el-input__inner) {
        border-radius:10px;
        padding:4px 7px;
        font-size:12px
    }
    :deep(.el-input__inner:focus) {
        border-shadow:0 0 0 2px rgba(237,64,20,.2);
    }
    :deep(.el-input__inner:hover) {
        border-color:#6586f9
    }
    :deep(.ivu-input){
        width:220px;
        border-radius:10px;
        padding:4px 7px;
        font-size:12px
    }
    :deep(.el-select-dropdown__list .el-select-dropdown__item){
        font-size:12px !important;
        height:30px;
        max-width:220px;
        line-height:30px
    }
    :deep(.el-select-dropdown){
        max-width:220px;
    }
    :deep(.el-select-dropdown__item.selected){
        color:#3f69f8;
        font-weight:400
    }
    :deep(.el-select-dropdown__empty){
        min-width:220px
    }

    :deep(.el-input__prefix){
        right:5px;
        left:auto
    }
    :deep(.el-range-input){
        font-size:12px;
        padding-top:1px
    }

    .selects {
      :deep(.el-input.el-input--medium.el-input--suffix) { // 调整箭头符号块的宽度
        width: 220px !important;
      }
      :deep(.el-input.el-input--medium.el-input--suffix) {
        .el-input__inner {                          // 调整输入框的宽高
          height: 30px !important;
          width: 220px !important;
        }
        :deep(.el-input__suffix-inner) {                   // 调整箭头符号的位置
          position: absolute;
          right: -45px;
        }
      }
      :deep(.el-select__tags) {                            // 调整输入框里面的多选不换行
        flex-wrap: nowrap !important;
      }
    }

}
</style>
